package com.lyn.tencent_health_code.service;

import com.lyn.tencent_health_code.dao.BaseDao;
import com.lyn.tencent_health_code.dao.HealthCodeRecordDao;
import com.lyn.tencent_health_code.database.HealthCodeRecord;
import com.lyn.tencent_health_code.utils.TextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.*;

/**
 * @author almost
 */
@Service
public class HealthCodeRecordService implements BaseDao<HealthCodeRecord, String> {

    @Autowired
    private HealthCodeRecordDao healthCodeRecordDao;

    @Override
    public HealthCodeRecord save(HealthCodeRecord healthCodeRecord) {
        if (TextUtils.isEmpty(healthCodeRecord.getId())) {
            healthCodeRecord.setId(UUID.randomUUID().toString().replace("-", ""));
        }
        if (healthCodeRecord.getTime() == 0) {
            healthCodeRecord.setTime(System.currentTimeMillis());
        }
        return healthCodeRecordDao.save(healthCodeRecord);
    }

    @Override
    public boolean deleteById(String id) {
        try {
            healthCodeRecordDao.deleteById(id);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public HealthCodeRecord update(HealthCodeRecord healthCodeRecord) {
        return healthCodeRecordDao.saveAndFlush(healthCodeRecord);
    }

    @Override
    public HealthCodeRecord findById(String id) {
        Optional<HealthCodeRecord> byId = healthCodeRecordDao.findById(id);
        if (byId.isPresent()) {
            return byId.get();
        }
        return null;
    }

    @Override
    public HealthCodeRecord findByName(String name) {
        return null;
    }

    @Override
    public boolean findByNameExist(String name) {
        return false;
    }

    @Override
    public List<HealthCodeRecord> findByPag(int page, int size) {
        Page<HealthCodeRecord> daoAll = healthCodeRecordDao.findAll(new Pageable() {
            @Override
            public int getPageNumber() {
                return page;
            }

            @Override
            public int getPageSize() {
                return size;
            }

            @Override
            public long getOffset() {
                return page * size - size;
            }

            @Override
            public Sort getSort() {
                return Sort.by(Sort.Direction.DESC, "time");
            }

            @Override
            public Pageable next() {
                return null;
            }

            @Override
            public Pageable previousOrFirst() {
                return null;
            }

            @Override
            public Pageable first() {
                return null;
            }

            @Override
            public Pageable withPage(int i) {
                return null;
            }

            @Override
            public boolean hasPrevious() {
                return false;
            }
        });
        List<HealthCodeRecord> healthCodeRecords = new ArrayList<>();
        Iterator<HealthCodeRecord> healthCodeRecordIterator = daoAll.iterator();
        while (healthCodeRecordIterator.hasNext()) {
            HealthCodeRecord healthCodeRecord = healthCodeRecordIterator.next();
            healthCodeRecords.add(healthCodeRecord);
        }
        return healthCodeRecords;
    }

    @Override
    public List<HealthCodeRecord> findByPag(int page, int size, int type) {
        return null;
    }

    @Override
    public long findByPagCount(int type) {
        return 0;
    }

    public long findByPagCount(String serialNumber) {
        Specification<HealthCodeRecord> codeRecordSpecification = new Specification<HealthCodeRecord>() {
            @Override
            public Predicate toPredicate(Root<HealthCodeRecord> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.equal(root.get("serialNumber"), serialNumber));
                return cq.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        };
        long count = healthCodeRecordDao.count(codeRecordSpecification);
        return count;
    }

    @Override
    public List<HealthCodeRecord> findByPag(int page, int size, String startTime, String endTime) {
        Specification<HealthCodeRecord> codeRecordSpecification = new Specification<HealthCodeRecord>() {
            @Override
            public Predicate toPredicate(Root<HealthCodeRecord> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.greaterThanOrEqualTo(root.get("time"), startTime));
                predicates.add(cb.lessThanOrEqualTo(root.get("time"), endTime));
                return cq.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        };
        Page<HealthCodeRecord> daoAll = healthCodeRecordDao.findAll(codeRecordSpecification,new Pageable() {
            @Override
            public int getPageNumber() {
                return page;
            }

            @Override
            public int getPageSize() {
                return size;
            }

            @Override
            public long getOffset() {
                return page * size - size;
            }

            @Override
            public Sort getSort() {
                return Sort.by(Sort.Direction.DESC, "time");
            }

            @Override
            public Pageable next() {
                return null;
            }

            @Override
            public Pageable previousOrFirst() {
                return null;
            }

            @Override
            public Pageable first() {
                return null;
            }

            @Override
            public Pageable withPage(int i) {
                return null;
            }

            @Override
            public boolean hasPrevious() {
                return false;
            }
        });
        List<HealthCodeRecord> healthCodeRecords = new ArrayList<>();
        Iterator<HealthCodeRecord> healthCodeRecordIterator = daoAll.iterator();
        while (healthCodeRecordIterator.hasNext()) {
            HealthCodeRecord healthCodeRecord = healthCodeRecordIterator.next();
            healthCodeRecords.add(healthCodeRecord);
        }
        return healthCodeRecords;
    }

    @Override
    public long findByPagCount(String startTime, String endTime) {
        Specification<HealthCodeRecord> codeRecordSpecification = new Specification<HealthCodeRecord>() {
            @Override
            public Predicate toPredicate(Root<HealthCodeRecord> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.greaterThanOrEqualTo(root.get("time"), startTime));
                predicates.add(cb.lessThanOrEqualTo(root.get("time"), endTime));
                return cq.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            }
        };
        long count = healthCodeRecordDao.count(codeRecordSpecification);
        return count;
    }

    @Override
    public List<HealthCodeRecord> findByPag(int page, int size, int type, String startTime, String endTime) {

        return null;
    }

    @Override
    public long findByPagCount(int type, String startTime, String endTime) {
        return 0;
    }

    @Override
    public long count() {
        return healthCodeRecordDao.count();
    }
}
